﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.FxCop.Sdk;
using Common.Configs;

namespace BovespaNamingRules
{
    public sealed class Rule_BovespaAvoidLongVariableNames : BaseAddIn.Rules.BaseRuleFXCop
    {
        #region Fields

        private int _lengthVariable;

        #endregion
        
        #region Constructor

        public Rule_BovespaAvoidLongVariableNames() :
            base("BovespaAvoidLongVariableNames", "BovespaNamingRules.BovespaNamingRules", typeof(Rule_BovespaAvoidLongVariableNames).Assembly)
        {
            this._lengthVariable = Settings.LengthVariable;
        }

        #endregion

        #region Public Override Methods

        public sealed override ProblemCollection Check(Member member)
        {
            switch (member.NodeType)
            {
                case NodeType.Method:
                    ExecCheckMethod(member);
                    break;
                case NodeType.Property:
                    ExecCheckProperty(member);
                    break;
                case NodeType.Field:
                    ExecCheckField(member);
                    break;
            }

            return this.Problems;
        }


        #endregion

        #region Private Methods

        private bool CkeckLongName(string name)
        {
            if (name.Length > this._lengthVariable)
                return false;
            else
                return true;
        }

        private void ExecCheckMethod(Member member)
        {
            Method method = member as Method;

            if (method != null)
            {
                if (method.DeclaringMember == null ||
                    (method.DeclaringMember != null &&
                    method.DeclaringMember.NodeType != NodeType.Property &&
                    !method.Name.Name.ToUpper().StartsWith("get_") &&
                    !method.Name.Name.ToUpper().StartsWith("set_")))
                {
                    foreach (Parameter param in method.Parameters)
                    {
                        if (!this.CkeckLongName(param.Name.Name))
                            AddError(member, "BovespaAvoidLongVariableNamesResolution2", param.Name.Name, member.DeclaringType.Name.Name, member.DeclaringType.Namespace.Name, this._lengthVariable.ToString());
                    }

                    this.VerifyLocal(method.Locals);
                }
            }
        }

        private void ExecCheckProperty(Member member)
        {
            PropertyNode property = member as PropertyNode;

            if (property != null)
            {
                if (!this.CkeckLongName(property.Name.Name))
                    AddError(member, "BovespaAvoidLongVariableNamesResolution2", property.Name.Name, member.DeclaringType.Name.Name, member.DeclaringType.Namespace.Name, this._lengthVariable.ToString());
            }
        }

        private void ExecCheckField(Member member)
        {
            Field field = member as Field;

            if (field != null)
            {
                if (!this.CkeckLongName(field.Name.Name))
                    AddError(member, "BovespaAvoidLongVariableNamesResolution2", field.Name.Name, member.DeclaringType.Name.Name, member.DeclaringType.Namespace.Name, this._lengthVariable.ToString());
            }
        }

        private void VerifyLocal(LocalCollection locals)
        {
            if (locals != null)
            {
                foreach (Local local in locals)
                {
                    if (!this.CkeckLongName(local.Name.Name))
                        AddError(local, "BovespaAvoidLongVariableNamesResolution1", local.Name.Name, this._lengthVariable.ToString());
                }
            }
        }

        #endregion
    }
}
